PROGRAM	CDTracker;
{$R CDTracker.Rsrc}
{$U-}

USES
    Memtypes,QuickDraw,OSIntf,ToolIntf,PackIntf;


CONST
    TextStatItem = 2;   {Item number of static text}
    textItem = 3;        {item number for editable text item}
TYPE
    ReadTOCBlk = record
    theBytes : packed array [0..3] of byte;
    end;
    twoBytes = ARRAY [0..1] of signedbyte;

VAR
    err : integer;
	 		DoErrDialPtr,DialPtr,oldPort : DialogPtr;
		 	DialTitle,GuessStr,RealStr : str255;
	 		isVis, DialGoAway : boolean;
	 		DialRefCon : longint;
	 		DialItemHit, DITLID : integer;
	 		DITLHndl : handle;
    CloseWind,PassWrdOK :boolean;
    x,y,z : integer;        {scratch ints}
    theType : integer;   {gives the type of the item requested}
    theTextHdl : handle;    {gives a handle to the item}
    txtBox : Rect;    {gives the display rectangle of the item}
    PBlkPtr     : ParmBlkPtr;
    Pblk        : ParamBlockRec;
    theStr : str255;
    VolRefN, FilRefN,DrvrRefNum : integer;
    MyBuffer : ptr;
    BigBuf,HowMuch : longint;
    MyFFSynthPtr : FFSynthPtr;
    SoundAway, NoMore : boolean;
    StartTrk,EndTrak,Minits,Secns,Framez,BCDTrackNo : signedbyte;
    NumTracks, TrkIndex : integer;
    EndOfDiskBlk : ReadTOCBlk;



		{------------------------------------------------------------------------------------}
	
  PROCEDURE debugger; INLINE $A9FF;

		{------------------------------------------------------------------------------------}

		PROCEDURE InitMac;

			BEGIN					   {InitMac}

   InitGraf (@thePort);          {the big five inits}
   InitFonts;
   InitWindows;
   TEInit;
   InitDialogs (nil);

			END;					   {InitMac}

		{------------------------------------------------------------------------------------}

FUNCTION BCDtoHex (SrcByte:signedbyte):integer;

VAR
    x,y : integer;

begin
    x := integer(SrcByte MOD 16);
    y := integer(SrcByte DIV 16);
    y := y*10;
    BCDtoHex := x+y;
end;

		{------------------------------------------------------------------------------------}

FUNCTION HextoBCD (SrcInt:integer):signedbyte;

VAR
    x,y : integer;
    z : signedbyte;

begin
    z := $0;
    x := SrcInt MOD 256;
    y := x;
    if y >= 10 then
    begin
        z := z + $10;
        repeat
            y := y-10;
            if y > 10 then z := z + $10;
        until (y < 10);
    end;
    HextoBCD := signedbyte(y)+z;
end;

		{------------------------------------------------------------------------------------}

PROCEDURE DoError (ErStr : str255; err : longint);

VAR
    NumStr : str255;

    Begin
        GetPort (oldPort);
        if err <> noerr then
        begin
        NumToString (err,NumStr);
        ErStr := Concat (ErStr,NumStr);
        end;
        DITLID := 257;
        DITLHndl := GetResource ('DITL', DITLID);
        err := ResError;
        if err = noerr then
        begin
        if DITLHndl <> nil then

        begin
            Hlock (DITLHndl);
            DoErrDialPtr := GetNewDialog (257,nil,WindowPtr(-1));
            If DoErrDialPtr <> nil then
            begin
            GetDItem (DoErrDialPtr, TextStatItem, theType, theTextHdl, txtBox);
            If theTextHdl <> nil then
            begin
     
            SetPort (DoErrDialPtr);

            SetIText (theTextHdl, ErStr);
            repeat
            ModalDialog (nil, DialItemHit);
            until DialItemHit <> 0;
            Case DialItemHit of  {1 = OK btn, 2 = message}
                1,2 : CloseDialog (DoErrDialPtr);
								
			  	      end; {case}
            end;
            end;
        end;
        end;
        setPort (oldPort);
     end;

		{------------------------------------------------------------------------------------}

PROCEDURE GetTrackInfo (dRefNum,trackNo:integer);

TYPE
    longintptr = ^ptr;
    bytePtr = ^signedbyte;
VAR
    PB : ParamBlockRec;
    theStr : str255;
    aByte : signedbyte;
    x,y,z : integer;
    DataPtr : longintptr;
    DataBlock : ReadTOCBlk;
    BytePoint : bytePtr;
    carry : boolean;

begin
carry := false;
    BCDTrackNo := HexToBCD (trackNo);
    PB.ioCompletion := nil;
    PB.ioRefNum := dRefNum;
    PB.csCode := 100;
    PB.csParam[0] := 3;
    DataPtr := @PB.csParam[1];
    DataPtr^ := @DataBlock;
    PB.csParam[3] := 4;
    bytePoint := @PB.csParam[4];
    bytePoint^ := signedbyte(BCDTrackNo);
    err := PBControl (@PB,false);
    if err = noerr then
    begin
        if trackNo = NumTracks then
        Begin
            BytePoint := @PB.csParam[1];
            BytePoint := bytePtr(longint(BytePoint)+1);
            BytePoint^ := EndOfDiskBlk.theBytes[0];
            BytePoint := bytePtr(longint(BytePoint)+1);
            BytePoint^ := EndOfDiskBlk.theBytes[1];
            BytePoint := bytePtr(longint(BytePoint)+1);
            BytePoint^ := EndOfDiskBlk.theBytes[2];
            BytePoint := bytePtr(longint(BytePoint)+1);
        end
        else
        begin
            PB.ioCompletion := nil;
            PB.ioRefNum := dRefNum;
            PB.csCode := 103;
            PB.csParam[0] := 2;
            PB.csParam[1] := 0;
            z := BCDToHex (BCDTrackNo);
            z := z+1;
            aByte := HexToBCD (z);
            PB.csParam[2] := aByte;
            PB.csParam[3] := 0;
            err := PBControl (@PB,false);
            if err = noerr then
                begin
                    PB.ioCompletion := nil;
                    PB.ioRefNum := dRefNum;
                    PB.csCode := 107;
                    err := PBControl (@PB,false);
                end
                else doError ('PBControl (103) error = ',err);
        end;
        if err = noerr then
        begin
            NumToString(longint(trackNo),theStr);
            GetDItem (DialPtr, 6, theType, theTextHdl, txtBox);
            If theTextHdl <> nil then SetIText (theTextHdl,theStr);
                
            aByte := DataBlock.theBytes[3];  {do frames first}
            x := BCDtoHex (aByte);
            aByte := signedbyte(twoBytes(PB.csParam[2])[1]);
            y := BCDtoHex (aByte);
            z := y-x;
            if (z < 0) then
            begin
                z := z + 74;   {74 frames/sec}
                carry := true;
            end
            else carry := false;
            NumToString(z,theStr);
            GetDItem (DialPtr, 9, theType, theTextHdl, txtBox);
            If theTextHdl <> nil then SetIText (theTextHdl,theStr);
                
            aByte := DataBlock.theBytes[2];  {do seconds second}
            x := BCDtoHex (aByte);
            aByte := signedbyte(twoBytes(PB.csParam[2])[0]);
            y := BCDtoHex (aByte);
            if carry then y := y-1;
            z := y-x;
            if (z < 0) then
            begin
                z := z + 60;    {60 seconds/minute}
                carry := true;
            end
            else carry := false;
            NumToString(z,theStr);
            GetDItem (DialPtr, 8, theType, theTextHdl, txtBox);
            If theTextHdl <> nil then SetIText (theTextHdl,theStr);
                
            aByte := DataBlock.theBytes[1];
            x := BCDtoHex (aByte);
            aByte := signedbyte(twoBytes(PB.csParam[1])[1]);
            y := BCDtoHex (aByte);
            if carry then y := y-1;
            z := y-x;
            NumToString(z,theStr);
            GetDItem (DialPtr, 7, theType, theTextHdl, txtBox);
            If theTextHdl <> nil then SetIText (theTextHdl,theStr);
        end
        else doError ('PBControl (107) error = ',err);
    end
    else doError ('PBControl (100,3) error = ',err);
end;
                
		{------------------------------------------------------------------------------------}

PROCEDURE GetCDInfo(dRefNum:integer;VAR StrtTrk,EndTrk:signedbyte);
    
VAR
    PB : ParamBlockRec;

begin
    PB.ioCompletion := nil;
    PB.ioRefNum := dRefNum;
    PB.csCode := 100;
    PB.csParam[0] := 1;
    err := PBControl (@PB,false);
    if err = noerr then
    begin
        StrtTrk := signedbyte(twoBytes(PB.csParam[0])[0]);
        EndTrk := signedbyte(twoBytes(PB.csParam[0])[1]);
    end
    else doError ('PBControl (100,1) error = ',err);
end;

		{------------------------------------------------------------------------------------}

PROCEDURE GetEndOfDisk (dRefNum:integer;VAR datablk:ReadTOCBlk);

VAR
    PB : ParamBlockRec;

begin
    PB.ioCompletion := nil;
    PB.ioRefNum := dRefNum;
    PB.csCode := 100;
    PB.csParam[0] := 2;
    err := PBControl (@PB,false);
    if err = noerr then
    begin
        datablk.theBytes[0] := signedbyte(twoBytes(PB.csParam[0])[0]);
        datablk.theBytes[1] := signedbyte(twoBytes(PB.csParam[0])[1]);
        datablk.theBytes[2] := signedbyte(twoBytes(PB.csParam[1])[0]);
        datablk.theBytes[3] := signedbyte(twoBytes(PB.csParam[1])[1]);
    end
    else doError ('PBControl (100,1) error = ',err);
end;

    

		{------------------------------------------------------------------------------------}

FUNCTION GetDrvr:Integer;

VAR
    MyReply : SFReply;
    Place : point;
    MyTypeList : SFTypeList;
    PB : HParamBlockRec;
    
Begin
    
    Place.v := 50;
    Place.h := 50;
    SFGetFile (Place,'',nil,-1,MyTypeList,nil,MyReply);
    if MyReply.good then
    begin
        PB.ioCompletion := nil;
        PB.ioNamePtr := nil;
        PB.ioVRefNum := MyReply.vRefNum;
        PB.ioVolIndex := 0;
        err := PBHGetVInfo (@PB,false);
        if err = noerr then GetDrvr := PB.ioVDRefNum
        else GetDrvr := 0;
    end
    else GetDrvr := 0;
end;

		{------------------------------------------------------------------------------------}

begin
    initmac;
    DITLID := 256;
    DITLHndl := GetResource ('DITL', DITLID);
    err := ResError;
    if err = noerr then
    begin
        if DITLHndl <> nil then
				    begin
            Hlock (DITLHndl);					
            DialPtr := GetNewDialog (256,nil,WindowPtr(-1));
            SetPort (DialPtr);
            If DialPtr <> nil then
            begin
                DrvrRefNum := GetDrvr;
                GetCDInfo (DrvrRefNum,StartTrk,EndTrak);
                x := BCDtoHex (EndTrak);
                y := BCDtoHex (StartTrk);
                NumTracks := x-y+1;
                GetTrackInfo (DrvrRefNum,1);
                TrkIndex := 1;
                GetEndOfDisk (DrvrRefNum,EndOfDiskBlk);
                CloseWind := False;
                repeat
                begin
                    repeat
                    ModalDialog (nil, DialItemHit);
                    until DialItemHit <> 0;
                    Case DialItemHit of  {1 = OK btn, 10 = message, 3 = edittext}
                    1 : begin
                            CloseDialog (DialPtr);
                            CloseWind := True;
                        end;
                    10 : begin
                            TrkIndex := TrkIndex + 1;
                            if TrkIndex > NumTracks then TrkIndex := 1;
                            GetTrackInfo (DrvrRefNum,TrkIndex);
                            If err <> noerr then trkIndex := trkIndex-1;
                        end;
                    end; {case}
                end;
                until closewind;
            end 
            else DoError ('DialPtr Nil',0);
            HUnlock (DITLHndl);
        end
        else DoError ('DITL Handle Nil',0);
    end
    else DoError ('Resource Error = ',err);
end.